home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mfs055 / minit.c < prev    next >
C/C++ Source or Header  |  1992-01-26  |  13KB  |  553 lines

  1. /* minit Minix INITializer . Freely distributable Minix filesys creator.
  2.  * Copyright S N Henson Nov 1991 .
  3.  * Use entirely at your own risk ! If it trashes your hard-drive then
  4.  * it isn't my fault ! 
  5.  */
  6.  
  7. /* Version 0.211 */
  8. /* Compile with gcc -O -o minit.ttp minit.c -liio */
  9.  
  10. #include <osbind.h>
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include <stdlib.h>
  16.  
  17. /* New extended  Rwabs  function , same as Rwabs except  sectors  can
  18.  * be specified as longs , this will be needed for large V2 filesystems.
  19.  * you will need to change this for other compilers ....
  20.  */
  21.  
  22. #define _XRwabs(a,b,c,d,e,f) \
  23. trap_13_wwlwwwl((short)(0x04),(short)(a),(long)(b),(short)(c),(short)(d)\
  24. ,(short)(e),(long)(f) )
  25.  
  26. #define trap_13_wwlwwwl(n, a, b, c, d, e, f)                \
  27. ({                                    \
  28.     register long retvalue __asm__("d0");                \
  29.     volatile short _a = (volatile short)(a);            \
  30.     volatile long  _b = (volatile long) (b);            \
  31.     volatile short _c = (volatile short)(c);            \
  32.     volatile short _d = (volatile short)(d);            \
  33.     volatile short _e = (volatile short)(e);            \
  34.     volatile long  _f = (volatile long) (f);            \
  35.                                         \
  36.     __asm__ volatile                        \
  37.     ("\
  38.         movl    %5,sp@-; \
  39.         movw    %4,sp@-; \
  40.         movw    %3,sp@-; \
  41.         movw    %2,sp@-; \
  42.         movl    %1,sp@-; \
  43.         movw    %0,sp@-    "                    \
  44.     :                          /* outputs */    \
  45.     : "g"(_a), "g"(_b), "g"(_c), "g"(_d), "g"(_e), "g"(_f) /* inputs  */ \
  46.     );                                \
  47.                                     \
  48.     __asm__ volatile                        \
  49.     ("\
  50.         movw    %1,sp@-; \
  51.         trap    #13;    \
  52.         addw    #18,sp "                    \
  53.     : "=r"(retvalue)            /* outputs */        \
  54.     : "g"(n)                /* inputs  */        \
  55.     : "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */    \
  56.     );                                \
  57.     retvalue;                            \
  58. })
  59.  
  60.  
  61. /* Change this if needed , but only if you know what you are doing */
  62. /* You shouldn't need to with the -n option though */
  63.  
  64. #define MNAME_MAX 14
  65.  
  66. int shift,drive=-1;
  67. long numblocks,numinodes,incr=1;
  68.  
  69. /* various flags */
  70. char protect,sonly,zbpb,v2,lrecno,tst;
  71.  
  72. unsigned char block_buf[1024];
  73.  
  74. /* Structures we will need */
  75.  
  76. typedef struct  {
  77.   unsigned short  s_ninodes;    /* # usable inodes on the minor device */
  78.   unsigned short  s_nzones;    /* total device size, including bit maps etc */
  79.   unsigned short s_imap_blks;    /* # of blocks used by inode bit map */
  80.   unsigned short s_zmap_blks;    /* # of blocks used by zone bit map */
  81.   unsigned short s_firstdatazn;    /* number of first data zone */
  82.   short int s_log_zsize;    /* log2 of blocks/zone */
  83.   unsigned long s_max_size;    /* maximum file size on this device */
  84.   short s_magic;        /* magic number to recognize super-blocks */
  85.   short pad;            /* padding */
  86.   long s_zones;            /* equivalent to 's_nzones' for V2 */
  87. } super_block;
  88.  
  89.  
  90.  
  91. typedef struct {        /* directory entry */
  92.   unsigned short d_inum;    /* inode number */
  93.   char d_name[MNAME_MAX];        /* character string */
  94. } dir_struct;
  95.  
  96. typedef struct {        /* disk inode. */
  97.   unsigned short i_mode;        /* file type, protection, etc. */
  98.   unsigned short i_uid;            /* user id of the file's owner */
  99.   unsigned long  i_size;        /* current file size in bytes */
  100.   unsigned long  i_mtime;        /* when was file data last changed */
  101.   unsigned char i_gid;            /* group number */
  102.   unsigned char i_nlinks;        /* how many links to this file */
  103.   unsigned short i_zone[9];    /* block nums for direct, ind, and dbl ind */
  104. } d_inode;
  105.  
  106. typedef struct {
  107. unsigned short i_mode;
  108. unsigned short i_nlinks;
  109. unsigned short i_uid;
  110. unsigned short i_gid;
  111. unsigned long i_size;
  112. unsigned long i_atime;
  113. unsigned long i_mtime;
  114. unsigned long i_ctime;
  115. long i_zone[10];
  116. } d_inode2;
  117.  
  118. /* prototypes */
  119.  
  120. #ifdef __STDC__
  121. # define    P(s) s
  122. #else
  123. # define P(s) ()
  124. #endif
  125.  
  126.  
  127. int main P((int argc , char **argv ));
  128. int nrwabs P((int rw , void *buf , unsigned count , long recno , int drive ));
  129. void get_block P((long num ));
  130. void put_block P((long num ));
  131. void check_lrecno P((void ));
  132. int warn P((void ));
  133.  
  134. #undef P
  135.  
  136. main(argc,argv)
  137. int argc;
  138. char **argv;
  139. {
  140.     extern int optind,opterr;
  141.     extern char *optarg;
  142.     int c ;
  143.     static char err=0;
  144.     int i,j;
  145.     unsigned short *bpb;
  146.     unsigned short ioff,zone1;
  147.         super_block *sblk=(super_block *)block_buf,csblk;
  148.         d_inode *rip=(d_inode *)block_buf;
  149.     d_inode2 *ripn=(d_inode2 *)block_buf;
  150.         dir_struct *dir=(dir_struct *)block_buf;
  151.     unsigned short *srt=(unsigned short *)block_buf;
  152.  
  153.     /* Parse command-line options */
  154.     opterr=0;
  155.     while((c=getopt(argc,argv,"b:B:i:I:n:pPSZtV"))!=EOF)
  156.     {
  157.             switch(c){
  158.  
  159.                 case 'B':
  160.             case 'b':
  161.             numblocks=atol(optarg);
  162.             break;
  163.  
  164.             case 'n':
  165.             incr=atol(optarg);
  166.             break;
  167.     
  168.             case 'i':
  169.             case 'I':
  170.             numinodes=atol(optarg);
  171.             break;
  172.  
  173.             case 'P':
  174.             protect=1;
  175.             break;
  176.  
  177.             case 'p':
  178.             protect=2;
  179.             break;
  180.  
  181.             case 'S':
  182.             sonly=1;
  183.             break;
  184.  
  185.             case 'Z':
  186.             zbpb=1;
  187.             break;    
  188.  
  189.             case 'V':
  190.             v2=1;
  191.             break;
  192.  
  193.             case 't':
  194.             tst=1;
  195.             break;
  196.  
  197.             case '?':
  198.             err=1;
  199.             break;
  200.         }
  201.     }
  202.  
  203.     if(argc-optind!=1 || err || (zbpb && protect) )
  204.     {
  205.         fprintf(stderr,"Minix-compatible filesystem initializer\n");
  206.         fprintf(stderr,"Copyright S N Henson Nov 1991\n");
  207.         fprintf(stderr,"Version 0.211\n"); 
  208.         fprintf(stderr,"Usage\t(auto)\t: minit drive\n");
  209.         fprintf(stderr,"\t(manual): minit -b blocks -i inodes drive\n");
  210.         fprintf(stderr,"Also :\t-S only write out super-block\n");
  211.         fprintf(stderr,"\t-P protect filesystem with null disk\n");
  212.         fprintf(stderr,"\t-p make null disk of existing filestystem\n");
  213.         fprintf(stderr,"\t-Z protect with zero BPB\n");
  214.         fprintf(stderr,"\t-V make a V2 filesystem\n");
  215.         fprintf(stderr,"\t-n dirincrement\n");
  216.         fprintf(stderr,"\t-t test for lrecno in driver software\n");
  217.         exit(1);
  218.     }
  219.     drive=(argv[optind][0] & ~32)-'A' ;
  220.  
  221.     /* Sanity checking time */
  222.  
  223.     if((incr < 1) || (incr > 16) || ( (incr) & (incr-1) ) )
  224.     {
  225.         fprintf(stderr,"Dirincrement must be a power of two between\n");
  226.         fprintf(stderr,"1 and 16 (inclusive)\n");
  227.         exit(1);
  228.     }
  229.  
  230.     if( (numinodes < 0) || (numinodes > 65535) )
  231.     {
  232.         fprintf(stderr,"Need at least 1 and no more than 65535 inodes\n");
  233.         exit(1);
  234.     }
  235.  
  236.     if(!(bpb=Getbpb(drive))) {
  237.         fprintf(stderr,"Drive %c : Bad or illegal BPB\n",drive+'A');
  238.         exit(1);
  239.     }
  240.     if(bpb[0]!=512 && bpb[0]!=1024) {
  241.         fprintf(stderr,"Sorry unsupported sector size: %d\n",bpb[0]);
  242.          exit(1);
  243.     }
  244.     if(bpb[0]==512)shift=1;
  245.     else if(protect)
  246.     {
  247.         fprintf(stderr,"Null disk requires 512 byte sectors\n");
  248.         exit(1);
  249.     }
  250.  
  251.     if(drive > 1 ) check_lrecno();
  252.  
  253.     if(tst)
  254.     {
  255.         if(lrecno) fprintf(stderr,"Lrecno supported by this setup\n");
  256.         else fprintf(stderr,"Lrecno not supported by this setup\n");
  257.         exit(0);
  258.     }
  259.  
  260.     /* Work out parameters */
  261.  
  262.     get_block(0);   /* Read in boot sector */
  263.     /* Get filesys size from bootsector if not given */
  264.     if(numblocks==0)
  265.     {
  266.         numblocks=(block_buf[19]+( ((long)block_buf[20])<<8))>>shift;
  267.         if(numblocks < 40 ){
  268.                  fprintf(stderr,"%ld blocks ? Is that bootsector OK ?\n",numblocks);
  269.                  exit(1);
  270.         }
  271.     }
  272.  
  273.     if(!v2 && (numblocks > 65535) ) {
  274.          fprintf(stderr,"V1 filesystems can be at most 65535 blocks\n");
  275.          exit(1);
  276.     }
  277.  
  278.     if( !lrecno && (numblocks > 65535) ) {
  279.          fprintf(stderr,"Filesystems bigger than 64MEG require lrecno\n");
  280.          exit(1);
  281.     }
  282.  
  283.     if( !lrecno && shift && (numblocks > 32767) ) {
  284.          fprintf(stderr,"Filesytems bigger than 32MEG require 1K sectors\n");
  285.          exit(1);        
  286.     }
  287.  
  288.     get_block(numblocks-1); /* Try to read last block */
  289.  
  290.     if(numinodes==0)
  291.     {
  292.         numinodes = numblocks/3;
  293.     
  294.         /* Round up inode number to nearest block */
  295.  
  296.         if(v2) numinodes = (numinodes + 15) & ~15;
  297.  
  298.         else numinodes=(numinodes + 31 ) & ~31;
  299.     }
  300.  
  301.     if(numinodes > 65535) numinodes=65535;
  302.  
  303.     if(protect==2)
  304.     {
  305.         get_block(1);
  306.         if( (sblk->s_magic != 0x137f) && (sblk->s_magic!=0x2468) )
  307.         {
  308.             fprintf(stderr,"Fatal: bad magic number\n");
  309.             exit(1);
  310.         }
  311.     }
  312.  
  313.     warn();
  314.  
  315.     /* Set up boot sector */
  316.  
  317.     if(!sonly && (protect || zbpb) )
  318.     {
  319.         get_block(0);
  320.         if(protect)
  321.         {
  322.             /* Make GEMDOS think we have a tiny partition */
  323.             /* With root directory immediately after super-block */
  324.             block_buf[16]=2;
  325.             block_buf[17]=16;
  326.             block_buf[18]=0;
  327.             block_buf[22]=1;
  328.             block_buf[23]=0;
  329.         }
  330.         else if(zbpb)
  331.         {
  332.             block_buf[16]=block_buf[17]=block_buf[18]=0;
  333.             block_buf[22]=block_buf[23]=0;
  334.         }
  335.         strcpy((char *)(&block_buf[2]),"MINIX");
  336.         put_block(0);
  337.     }
  338.  
  339.  
  340.     /* OK lets work out some stuff */
  341.  
  342.     if(protect==2) get_block(1);
  343.     else
  344.     {
  345.         bzero(block_buf,1024l);
  346.         /* Super block */
  347.             sblk->s_ninodes=numinodes;
  348.             if(v2) sblk->s_zones=numblocks;
  349.         else sblk->s_nzones=numblocks;
  350.             sblk->s_imap_blks=(numinodes+8192)/8192;
  351.         sblk->s_zmap_blks=(numblocks+8191)/8192;
  352.         sblk->s_firstdatazn=2+sblk->s_imap_blks+sblk->s_zmap_blks
  353.             + ( v2 ? ((numinodes+15)/16) : ((numinodes+31)/32)) ;
  354.         sblk->s_log_zsize=0;
  355.         sblk->s_max_size= v2 ? 0x4041c00l : 0x10081c00l;
  356.         sblk->s_magic= v2 ? 0x2468 : 0x137f;
  357.     }
  358.  
  359.     /* If protecting fill up the pseudo root directory with vol names */
  360.     if(protect)
  361.     {
  362.         bzero(&block_buf[512],512);
  363.         for(i=512;i<1024;i+=32) 
  364.         {
  365.             strncpy((char*)&block_buf[i],"MINIXFS    ",11);   
  366.             block_buf[i+11]=0x08;
  367.         }
  368.     }
  369.  
  370.     put_block(1);
  371.  
  372.     if( sonly || protect==2 ) exit(0);    
  373.  
  374.     csblk=*sblk;
  375.  
  376.     ioff=2+sblk->s_imap_blks+sblk->s_zmap_blks;
  377.     zone1=sblk->s_firstdatazn;
  378.  
  379.     bzero(block_buf,1024l);
  380.  
  381.     /* Inode bitmaps */
  382.  
  383.     for(i=2;i<2+csblk.s_imap_blks;i++)
  384.     {
  385.         long icount=numinodes+1;
  386.         if(i==2)
  387.         {
  388.             srt[0]=3;
  389.         }
  390.         if(icount < 8192) /* Need to mark dead inodes as used */
  391.         {
  392.             if(icount & 15)
  393.             {
  394.                 srt[icount/16] = 0xffff << (icount & 15);
  395.                 icount+= 16 - (icount & 15);
  396.             }
  397.             for(j=icount/16;j<512;j++)srt[j]=0xffff;
  398.         }
  399.         put_block(i);
  400.         if(i==2)srt[0]=0;
  401.         icount-=8192;
  402.     }        
  403.  
  404.     bzero(block_buf,1024l);
  405.  
  406.         /* Zone bitmaps */
  407.  
  408.     for(i=2+csblk.s_imap_blks;i<ioff;i++)
  409.     {
  410.         long zcount=numblocks+1-csblk.s_firstdatazn;
  411.         if(i==2+csblk.s_imap_blks)
  412.         {
  413.             srt[0]=3;
  414.         }
  415.         if(numblocks < 8192) /* Need to mark dead zones as used */
  416.         {
  417.             if(zcount & 15)
  418.             {
  419.                 srt[zcount/16] = 0xffff << (zcount & 15);
  420.                 zcount+= 16 - (zcount & 15);
  421.             }
  422.             for(j=zcount/16;j<512;j++)srt[j]=0xffff;
  423.         }
  424.         put_block(i);
  425.         if(i==2+csblk.s_imap_blks)srt[0]=0;
  426.         zcount-=8192;
  427.     }        
  428.  
  429.     bzero(block_buf,1024l);
  430.  
  431.     /* Initialise inodes */
  432.     
  433.     for(i=ioff;i<ioff+
  434.         (v2 ? ((numinodes +15)/16) : ((numinodes+31)/32 )) ;i++)
  435.     {
  436.         if(i==ioff) /* Root inode , initialise it properly */
  437.         {
  438.             if(v2)
  439.             {
  440.                 ripn->i_mode=040777; /* Directory */
  441.                 ripn->i_size=32*incr;
  442.                 ripn->i_mtime=time((time_t *)0);
  443.                 ripn->i_ctime=ripn->i_mtime;
  444.                 ripn->i_atime=ripn->i_mtime;
  445.                 ripn->i_nlinks=2;
  446.                 ripn->i_zone[0]=zone1;
  447.             }
  448.             else
  449.             {
  450.                 rip->i_mode=040777; /* Directory */
  451.                 rip->i_size=32*incr;
  452.                 rip->i_mtime=time((time_t *)0);
  453.                 rip->i_nlinks=2;
  454.                 rip->i_zone[0]=zone1;
  455.             }
  456.         }    
  457.         put_block(i);
  458.         if(i==ioff)bzero(block_buf,1024l);
  459.     }
  460.  
  461.     bzero(block_buf,1024l);
  462.     /* And finally the root directory */
  463.     dir[0].d_inum=1;
  464.     strcpy(dir[0].d_name,".");
  465.     dir[incr].d_inum=1;
  466.     strcpy(dir[incr].d_name,"..");
  467.     put_block(zone1);
  468.     fprintf(stderr,"Initialised OK.\n");
  469.     fprintf(stderr,"%ld Blocks , %ld Inodes.\n",numblocks,numinodes);
  470.     exit(0);
  471. }
  472.  
  473. int nrwabs(rw,buf,count,recno,dev)
  474. int rw;
  475. void *buf;
  476. unsigned count;
  477. long recno;
  478. int dev;
  479. {
  480.     if(lrecno && (dev > 1) ) 
  481.         return (_XRwabs(rw,buf,count,-1,dev,recno) );
  482.     else return (Rwabs(rw,buf,count,(unsigned)(recno),dev) );
  483. }
  484.  
  485. void get_block(num)
  486. long num;
  487. {
  488.     
  489.  
  490.     if(nrwabs(2,block_buf,1<<shift,num<<shift,drive))
  491.     {
  492.         fprintf(stderr,"Fatal Read Error block %d\n",num);
  493.         exit(0);
  494.     }
  495. }
  496.  
  497.  
  498.  
  499.  
  500. void put_block(num)
  501. long num;
  502. {
  503.     if(nrwabs(3,block_buf,1<<shift,num<<shift,drive))
  504.     {
  505.         fprintf(stderr,"Fatal Write Error block %d\n",num);
  506.         exit(0);
  507.     }
  508. }
  509.  
  510. /* entirely unoffical attempt to check for the existance of 'lrecno' */
  511.  
  512. char block_buf2[1024];
  513.  
  514. void check_lrecno()
  515. {
  516.     /* read in boot block */
  517.     if(Rwabs(2,block_buf,1<<shift,0,drive)) return;
  518.  
  519.     /* read it in with lrecno */    
  520.     if( _XRwabs(2,block_buf2,1<<shift,-1,drive,0l) ) return;
  521.  
  522.     /* Compare the two */
  523.     if(bcmp(block_buf,block_buf2,1024)) return;
  524.  
  525.     /* read in next sector with lrecno */
  526.  
  527.     if(_XRwabs(2,block_buf2,1<<shift,-1,drive,1l)) return;
  528.  
  529.     /* compare the two */
  530.  
  531.     if(!bcmp((char *)block_buf,block_buf2,1024)) return;
  532.  
  533.     lrecno=1;
  534.  
  535.     return;
  536.  
  537. }
  538.  
  539. warn()
  540. {
  541.     int ch;
  542.     fprintf(stderr,"WARNING ! THIS %s TOTALLY DESTROY ANY DATA ON ",
  543.                     (sonly || protect) ? "MAY":"WILL");
  544.     fprintf(stderr,"DRIVE %c !\n",drive+'A');
  545.     fprintf(stderr,"Are you ABSOLUTELY SURE you want to do this (y/n)?\n");
  546.     ch=Crawcin() & 0xff ;
  547.     if(ch!='Y' && ch!='y')
  548.     {
  549.         fprintf(stderr,"Aborted\n");
  550.         exit(0);
  551.     }
  552. }
  553.